home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / TUT2NEW.ZIP / TUT2.CPP < prev    next >
C/C++ Source or Header  |  1994-11-30  |  20KB  |  507 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //                                                                         //
  3. // TUTPROG2.CPP - VGA Trainer Program 2 (in Turbo C++ 3.0)                 //
  4. //                                                                         //
  5. // "The VGA Trainer Program" is written by Denthor of Asphyxia. However it //
  6. // was limited to Pascal only in its first run.  All I have done is taken  //
  7. // his original release, translated it to C++ and touched up a few things. //
  8. // I take absolutely no credit for the concepts presented in this code and //
  9. // am NOT the person to ask for help if you are having trouble.            //
  10. //                                                                         //
  11. // Program Notes : This program presents many new concepts, including:     //
  12. //                 line drawing, pallette manipulation, and fading.        //
  13. //                                                                         //
  14. //                 If you are compiling this code command line, be sure to //
  15. //                 use the "-ml" parameter (large memory model).           //
  16. //                 Otherwise, the program will compile and link, but will  //
  17. //                 lock up your system.                                    //
  18. //                                                                         //
  19. // Author        : Grant Smith (Denthor) - denthor@beastie.cs.und.ac.za    //
  20. // Translator    : Christopher G. Mann   - r3cgm@dax.cc.uakron.edu         //
  21. //                                                                         //
  22. // Last Modified : November 29, 1994                                       //
  23. //                                                                         //
  24. /////////////////////////////////////////////////////////////////////////////
  25.  
  26.  
  27. //               //
  28. // INCLUDE FILES //
  29. //               //
  30.  
  31.   #include <conio.h>
  32.               // getch(), clrscr()
  33.   #include <dos.h>
  34.               // MK_FP, Geninterrupt()
  35.   #include <math.h>
  36.               // floor(), ceil()
  37.   #include <mem.h>
  38.               // memset(), movmem()
  39.   #include <iostream.h>
  40.               // cout
  41.   #include <stdlib.h>
  42.               // abs(), rand()
  43.  
  44.  
  45. //                     //
  46. // FUNCTION PROTOTYPES //
  47. //                     //
  48.  
  49.   // MODE SETTING FUNCTIONS
  50.   void SetMCGA();
  51.   void SetText();
  52.  
  53.   // PALLETTE FUNCTIONS
  54.   void GrabPallette();
  55.   void GetPal (unsigned char ColorNo,  unsigned char &R,
  56.            unsigned char &G,       unsigned char &B);
  57.   void Pal    (unsigned char ColorNo,  unsigned char R,
  58.            unsigned char G,        unsigned char B);
  59.   void PalPlay  ();
  60.   void Fadeup   ();
  61.   void FadeDown ();
  62.   void Blackout ();
  63.   void RestorePallette();
  64.  
  65.   // SMALL UTILITY FUNCTIONS
  66.   int  sgn  (long a);
  67.   int  round(long a);
  68.  
  69.   // DRAWING FUNCTIONS
  70.   void Putpixel (int x, int y, unsigned char Col);
  71.   void Line(int a, int b, int c, int d, int col);
  72.   void WaitRetrace();
  73.  
  74.   // MID-LEVEL (COMBINATION) FUNCTIONS
  75.   void SetUpScreen();
  76.   void HiddenScreenSetup();
  77.  
  78.  
  79. //                              //
  80. // GLOBAL VARIABLE DECLARATIONS //
  81. //                              //
  82.  
  83.   // declare a pointer to the offset of VGA memory
  84.   unsigned char *vga = (unsigned char *) MK_FP(0xA000, 0);
  85.  
  86.   // This declares the PALL variable. 0 to 255 signifies the colors of the
  87.   // pallette, 1 to 3 signifies the Red, Green and Blue values. I am
  88.   // going to use this as a sort of "virtual pallette", and alter it
  89.   // as much as I want, then suddenly bang it to screen. Pall2 is used
  90.   // to "remember" the origional pallette so that we can restore it at
  91.   // the end of the program. */
  92.   unsigned char Pall[256][3], Pall2[256][3];
  93.  
  94.  
  95. ///////////////////////////////////////////////////////////////////////////////
  96. //                                                                           //
  97. //                                MAIN FUNCTION                              //
  98. //                                                                           //
  99. ///////////////////////////////////////////////////////////////////////////////
  100.  
  101. void main() {
  102.  
  103.   clrscr();
  104.   cout << "This program will draw lines of different colors across the\n"
  105.        << "screen and change them only by changing their pallette values.\n"
  106.        << "The nice thing about using the pallette is that one pallette\n"
  107.        << "change changes the same color over the whole screen, without\n"
  108.        << "you having to redraw it. Because I am using a WaitRetrace\n"
  109.        << "command, turning on and off your turbo during the demonstration\n"
  110.        << "should have no effect." << endl << endl;
  111.  
  112.   cout << "The second part of the demo blacks out the screen using the\n"
  113.        << "pallette, fades in the screen, waits for a keypress, then fades\n"
  114.        << "it out again. I haven''t put in any delays for the fadein/out,\n"
  115.        << "so you will have to put them in yourself to get to the speed\n"
  116.        << "you like. Have fun and enjoy! ;-)" << endl << endl << endl;
  117.   cout << "Hit any key to continue ...";
  118.   getch();
  119.  
  120.   SetMCGA();
  121.   GrabPallette();
  122.   SetUpScreen();
  123.  
  124.   while (!kbhit()) PalPlay();
  125.     getch();  // once a key is pressed, be sure to clear the keyboard buffer
  126.  
  127.   Blackout();
  128.   HiddenScreenSetup();
  129.   Fadeup();
  130.   getch();
  131.   FadeDown();
  132.   getch();
  133.  
  134.   RestorePallette();
  135.   SetText();
  136.   cout << "All done. This concludes the second sample program in the ASPHYXIA\n"
  137.        << "Training series. You may reach DENTHOR under the name of GRANT\n"
  138.        << "SMITH on the MailBox BBS, or leave a message to ASPHYXIA on the\n"
  139.        << "ASPHYXIA BBS. Get the numbers from Roblist, or write to :\n"
  140.        << "             Grant Smith\n"
  141.        << "             P.O. Box 270\n"
  142.        << "             Kloof\n"
  143.        << "             3640\n"
  144.        << "I hope to hear from you soon!" << endl << endl << endl;
  145.  
  146.   cout << "Hit any key to exit ...";
  147.   getch();
  148. }
  149.  
  150. /////////////////////////////////////////////////////////////////////////////
  151. //                                                                         //
  152. // SetMCGA() - This function gets you into 320x200x256 mode.               //
  153. //                                                                         //
  154. /////////////////////////////////////////////////////////////////////////////
  155.  
  156. void SetMCGA() {
  157.   _AX = 0x0013;
  158.   geninterrupt (0x10);
  159. }
  160.  
  161. /////////////////////////////////////////////////////////////////////////////
  162. //                                                                         //
  163. // SetText() - This function gets you into text mode.                      //
  164. //                                                                         //
  165. /////////////////////////////////////////////////////////////////////////////
  166.  
  167. void SetText() {
  168.   _AX = 0x0003;
  169.   geninterrupt (0x10);
  170. }
  171.  
  172.  
  173. /////////////////////////////////////////////////////////////////////////////
  174. //                                                                         //
  175. // GrabPallette() - This function retrieves the current pallette.          //
  176. //                                                                         //
  177. /////////////////////////////////////////////////////////////////////////////
  178.  
  179. void GrabPallette() {
  180.  
  181.   for(int loop1=0;loop1<256;loop1++)
  182.     GetPal(loop1,Pall2[loop1][0],Pall2[loop1][1],Pall2[loop1][2]);
  183.  
  184. }
  185.  
  186. /////////////////////////////////////////////////////////////////////////////
  187. //                                                                         //
  188. // GetPal() - This reads the values of the Red, Green, and Blue values of  //
  189. //            a certain color.  This function uses pass-by-reference.      //
  190. //                                                                         //
  191. /////////////////////////////////////////////////////////////////////////////
  192.  
  193. void GetPal(unsigned char ColorNo, unsigned char &R,
  194.         unsigned char &G,      unsigned char &B) {
  195.  
  196.   outp (0x03C7,ColorNo); // here is the pallette color I want read
  197.   R = inp (0x03C9);
  198.   G = inp (0x03C9);
  199.   B = inp (0x03C9);
  200.  
  201. }
  202.  
  203. /////////////////////////////////////////////////////////////////////////////
  204. //                                                                         //
  205. // Pal() - This sets the Red, Green, and Blue values of a certain color.   //
  206. //                                                                         //
  207. /////////////////////////////////////////////////////////////////////////////
  208.  
  209. void Pal(unsigned char ColorNo, unsigned char R,
  210.      unsigned char G,       unsigned char B) {
  211.  
  212.   outp (0x03C8,ColorNo); // here is the pallette color I want to set
  213.   outp (0x03C9,R);
  214.   outp (0x03C9,G);
  215.   outp (0x03C9,B);
  216.  
  217. }
  218.  
  219. /////////////////////////////////////////////////////////////////////////////
  220. //                                                                         //
  221. // PalPlay() - This function mucks about with our "virtual pallette", then //
  222. //             shoves it to the screen.                                    //
  223. //                                                                         //
  224. /////////////////////////////////////////////////////////////////////////////
  225.  
  226. void PalPlay() {
  227.  
  228. unsigned char Tmp[3];
  229.  
  230.   // This copies color 200 from our virtual pallette to the Tmp variable.
  231.   _fmemmove(Tmp,Pall[200],3);
  232.  
  233.   // This moves the entire virtual pallette up one color.
  234.   _fmemmove(Pall[2],Pall[1],199*3);
  235.  
  236.   // This copies the Tmp variable to the bottom of the virtual pallette.
  237.   // Don't change 0: leave this always black to not change overscan color.
  238.   _fmemmove(Pall[1],Tmp,3);
  239.  
  240.   WaitRetrace();
  241.   for (int loop1=0;loop1<256;loop1++)
  242.    Pal(loop1,Pall[loop1][0], Pall[loop1][1], Pall[loop1][2]);
  243.  
  244. }
  245.  
  246. /////////////////////////////////////////////////////////////////////////////
  247. //                                                                         //
  248. // Fadeup() - This function slowly fades up the new screen                 //
  249. //                                                                         //
  250. /////////////////////////////////////////////////////////////////////////////
  251.  
  252. void Fadeup() {
  253.  
  254. //This is temporary storage for the values of a color
  255. unsigned char Tmp[3];
  256.  
  257.   // A color value for Red, green or blue is 0 to 63, so this loop only
  258.   // need be executed a maximum of 64 times.
  259.   for(int loop1=0;loop1<64;loop1++) {
  260.  
  261.     WaitRetrace();
  262.  
  263.     for(int loop2=0; loop2<256; loop2++) {
  264.       GetPal(loop2,Tmp[0],Tmp[1],Tmp[2]);
  265.  
  266.       // If the Red, Green or Blue values of color loop2 are less then they
  267.       // should be, increase them by one.
  268.       if ((Tmp[0] < Pall2[loop2][0]) && (Tmp[0] < 63)) Tmp[0]++;
  269.       if ((Tmp[1] < Pall2[loop2][1]) && (Tmp[1] < 63)) Tmp[1]++;
  270.       if ((Tmp[2] < Pall2[loop2][2]) && (Tmp[2] < 63)) Tmp[2]++;
  271.  
  272.       // Set the new, altered pallette color.
  273.       Pal (loop2,Tmp[0],Tmp[1],Tmp[2]);
  274.     }
  275.   }
  276. }
  277.  
  278. /////////////////////////////////////////////////////////////////////////////
  279. //                                                                         //
  280. // FadeDown() - This function fades the screen out to black.               //
  281. //                                                                         //
  282. /////////////////////////////////////////////////////////////////////////////
  283.  
  284. void FadeDown() {
  285.  
  286. // This is temporary storage for the values of a color
  287. unsigned char Tmp[3];
  288.  
  289.   for(int loop1=0; loop1<64; loop1++) {
  290.  
  291.     WaitRetrace();
  292.  
  293.     for(int loop2=0; loop2<256; loop2++) {
  294.       GetPal(loop2,Tmp[0],Tmp[1],Tmp[2]);
  295.  
  296.       // If the Red, Green or Blue values of color loop2 are not yet zero,
  297.       // then, decrease them by one.
  298.       if (Tmp[0] > 0) Tmp[0]--;
  299.       if (Tmp[1] > 0) Tmp[1]--;
  300.       if (Tmp[2] > 0) Tmp[2]--;
  301.  
  302.       // Set the new, altered pallette color.
  303.       Pal(loop2,Tmp[0],Tmp[1],Tmp[2]);
  304.     }
  305.   }
  306. }
  307.  
  308. /////////////////////////////////////////////////////////////////////////////
  309. //                                                                         //
  310. // Blackout() - This function just clears the screen.                      //
  311. //                                                                         //
  312. /////////////////////////////////////////////////////////////////////////////
  313.  
  314. void Blackout() {
  315.  
  316.   WaitRetrace();
  317.   for (int loop1=0;loop1<256;loop1++)
  318.     Pal (loop1,0,0,0);
  319.  
  320. }
  321.  
  322. /////////////////////////////////////////////////////////////////////////////
  323. //                                                                         //
  324. // RestorePallette() - This function restores the origional pallette.      //
  325. //                                                                         //
  326. /////////////////////////////////////////////////////////////////////////////
  327.  
  328. void RestorePallette() {
  329.  
  330.   WaitRetrace();
  331.   for(int loop1=0; loop1<255; loop1++)
  332.     Pal(loop1,Pall2[loop1][0],Pall2[loop1][1],Pall2[loop1][2]);
  333.  
  334. }
  335.  
  336.  
  337. /////////////////////////////////////////////////////////////////////////////
  338. //                                                                         //
  339. // sgn() - This function is used by Line() to determine the sign of a long //
  340. //                                                                         //
  341. /////////////////////////////////////////////////////////////////////////////
  342.  
  343. int sgn (long a) {
  344.  
  345.   if (a > 0) return +1;
  346.   else if (a < 0) return -1;
  347.   else return 0;
  348.  
  349. }
  350.  
  351. /////////////////////////////////////////////////////////////////////////////
  352. //                                                                         //
  353. // round() - This function is used by Line() to round a long to the        //
  354. //           nearest integer.                                              //
  355. //                                                                         //
  356. /////////////////////////////////////////////////////////////////////////////
  357.  
  358. int round (long a) {
  359.   if ( (a - (int)a) < 0.5) return floor(a);
  360.     else return ceil(a);
  361. }
  362.  
  363.  
  364. /////////////////////////////////////////////////////////////////////////////
  365. //                                                                         //
  366. // Putpixel() - This puts a pixel on the screen by writing directly to     //
  367. //              memory.                                                    //
  368. //                                                                         //
  369. /////////////////////////////////////////////////////////////////////////////
  370.  
  371. void Putpixel (int x, int y, unsigned char Col) {
  372.  
  373.   memset(vga+(x+(y*320)),Col,1);
  374.  
  375. }
  376.  
  377. /////////////////////////////////////////////////////////////////////////////
  378. //                                                                         //
  379. // Line() - This draws a line from a,b to c,d of color col.                //
  380. //          This function will be explained in more detail in tut3new.zip  //
  381. //                                                                         //
  382. /////////////////////////////////////////////////////////////////////////////
  383.  
  384. void Line(int a, int b, int c, int d, int col) {
  385.  
  386. long u,s,v,d1x,d1y,d2x,d2y,m,n;
  387. int  i;
  388.  
  389.   u   = c-a;      // x2-x1
  390.   v   = d-b;      // y2-y1
  391.   d1x = sgn(u);   // d1x is the sign of u (x2-x1) (VALUE -1,0,1)
  392.   d1y = sgn(v);   // d1y is the sign of v (y2-y1) (VALUE -1,0,1)
  393.   d2x = sgn(u);   // d2x is the sign of u (x2-x1) (VALUE -1,0,1)
  394.   d2y = 0;
  395.   m   = abs(u);   // m is the distance between x1 and x2
  396.   n   = abs(v);   // n is the distance between y1 and y2
  397.  
  398.   if (m<=n) {     // if the x distance is greater than the y distance
  399.     d2x = 0;
  400.     d2y = sgn(v); // d2y is the sign of v (x2-x1) (VALUE -1,0,1)
  401.     m   = abs(v); // m is the distance between y1 and y2
  402.     n   = abs(u); // n is the distance between x1 and x2
  403.   }
  404.  
  405.   s = (int)(m / 2); // s is the m distance (either x or y) divided by 2
  406.  
  407.   for (i=0;i<round(m);i++) { // repeat this loop until it
  408.                  // is = to m (y or x distance)
  409.     Putpixel(a,b,col);       // plot a pixel at the original x1, y1
  410.     s += n;                  // add n (dis of x or y) to s (dis of x of y)
  411.     if (s >= m) {            // if s is >= m (distance between y1 and y2)
  412.       s -= m;
  413.       a += d1x;
  414.       b += d1y;
  415.     }
  416.     else {
  417.       a += d2x;
  418.       b += d2y;
  419.     }
  420.   }
  421.  
  422. }
  423.  
  424. /////////////////////////////////////////////////////////////////////////////
  425. //                                                                         //
  426. // WaitRetrace() - This waits until you are in a Verticle Retrace ...      //
  427. //            this means that all screen manipulation you do only     //
  428. //           appears on screen in the next verticle retrace ... this //
  429. //           removes most of the "fuzz" that you see on the screen   //
  430. //           when changing the pallette. It unfortunately slows down //
  431. //           your program by "synching" your program with your       //
  432. //           monitor card ... it does mean that the program will run //
  433. //           at almost the same speed on different speeds of         //
  434. //           computers which have similar monitors.  In our          //
  435. //           SilkyDemo, we used a WaitRetrace, and it therefore      //
  436. //           runs at the same (fairly fast) speed when Turbo is on   //
  437. //           or off.                                                 //
  438. //                                                                         //
  439. /////////////////////////////////////////////////////////////////////////////
  440.  
  441. void WaitRetrace() {
  442.  
  443.   _DX = 0x03DA;
  444.  
  445.   l1: asm {
  446.     in  al,dx;
  447.     and al,0x08;
  448.     jnz l1;
  449.       }
  450.  
  451.   l2: asm {
  452.     in  al,dx;
  453.     and al,0x08;
  454.     jz  l2;
  455.       }
  456. }
  457.  
  458.  
  459. /////////////////////////////////////////////////////////////////////////////
  460. //                                                                         //
  461. // SetUpScreen() - This gets our screen ready by setting up the pallette   //
  462. //                 and drawing the lines.                                  //
  463. //                                                                         //
  464. /////////////////////////////////////////////////////////////////////////////
  465.  
  466. void SetUpScreen() {
  467.  
  468.   // Clear the entire PALL variable to zero.
  469.   _fmemset(Pall,0,sizeof(Pall));
  470.  
  471.   // This sets colors 0 to 200 in the PALL variable to values between
  472.   // 0 to 63. the modulus function gives you the remainder of a division,
  473.   // ie. 105 % 10 = 5.
  474.   for (int loop = 0; loop < 201;loop++)
  475.     Pall[loop][0] = loop % 64;
  476.  
  477.   for (loop = 0; loop < 321; loop++) {
  478.  
  479.     // These two lines start drawing lines from the left and the right
  480.     // hand sides of the screen, using colors 1 to 199. Look at these
  481.     // two lines and understand them.
  482.     Line(319,199,320-loop,0,(loop % 199) + 1);
  483.     Line(0,0,loop,199,(loop % 199) + 1);
  484.  
  485.     // This calls the PalPlay function.
  486.     PalPlay();
  487.   }
  488.  
  489. }
  490.  
  491. /////////////////////////////////////////////////////////////////////////////
  492. //                                                                         //
  493. // HiddenScreenSetup() - This function sets up the screen while it is      //
  494. //                       blacked out, so that the user can't see what is   //
  495. //                       happening.                                        //
  496. //                                                                         //
  497. /////////////////////////////////////////////////////////////////////////////
  498.  
  499. void HiddenScreenSetup() {
  500.  
  501.   for (int loop1=0; loop1<320; loop1++)
  502.     for (int loop2=0; loop2<200; loop2++)
  503.       Putpixel (loop1,loop2, rand());
  504.  
  505. }
  506.  
  507.